import { Injectable } from '@nestjs/common';
import * as dayjs from 'dayjs';
import { Device } from 'src/entities/Device';
import { IotSim } from 'src/entities/IotSim';
import { DeviceModelService } from 'src/model/device-model/device-model.service';
import { IotSimModelService } from 'src/model/iot-sim-model/iot-sim-model.service';
import { getTime } from 'src/utils';
import { Connection, FindConditions, LessThanOrEqual, Like, MoreThanOrEqual } from 'typeorm';
import { AddDto, EditDto, ListDto } from './dto/Common.dto';

@Injectable()
export class IotSimService {
    constructor(
        private iotSimModelService:IotSimModelService,
        private deviceModelService:DeviceModelService,
        private connection:Connection
    ){}


    async iotsimList(dto:ListDto) {
        let where:FindConditions<IotSim> = {}

        if(dto.cardNo) {
            where.cardNo = dto.cardNo
        }

        if(dto.startExpire && dto.endExpire && (dto.startExpire == dto.endExpire)) {
            where.expireIn = dayjs(dto.startExpire).unix()
        }else {
            if(dto.startExpire) {
                where.expireIn = MoreThanOrEqual(dayjs(dto.startExpire).unix())
            }
    
            if(dto.endExpire) {
                where.expireIn = LessThanOrEqual(dayjs(dto.endExpire).unix())
            }
        }
        

        let result:PaginationResult<IotSim> = {
            total : 0,
            rows : []
        } 
        result.total = await this.iotSimModelService.count(where)

        if(result.total > 0) {
            result.rows = await this.iotSimModelService.pagination(dto.pageNo, dto.pageSize, where, null, {id : 'DESC'})
        }

        return result
    }

    async querySimByCardNo(cardNo:string) {
        let rows = await this.iotSimModelService.find({cardNo : Like(cardNo + '%')}, ['cardNo', 'id'], 0, 10, {id : 'DESC'})
        return rows
    }

    cardNoIsExists(cardNo:string) {
        return this.iotSimModelService.isExistsByWhere({cardNo : cardNo})
    }

    dd(){
        // for(let i = 10000; i <= 20000; i ++) {
        //     const no = String(i).padEnd(20, '0')
        //     this.iotSimModelService.insert({cardNo : no}).then(id => {
        //         this.deviceModelService.insert({simCardNo : no, simId : id})
        //     })
        // }

        // this.iotSimModelService.find().then(async (rows) => {
        //     for(let i = 0; i <= 10000; i ++) {
        //         const no = String(i).padEnd(20, '0')
        //         await this.deviceModelService.insert({simCardNo : rows[i].cardNo, simId : rows[i].id})
        //     }
        // })
    }

    async add(dto:AddDto) {
        let data:{[key in keyof IotSim]? : IotSim[key]} = {
            cardNo : dto.cardNo,
            createTime : getTime()
        }
        if(dto.expireIn) {
            data.expireIn = dayjs(dto.expireIn).unix()
        }
        let id = await this.iotSimModelService.insert(data)
        return id

    }

    async edit(id:number, dto:EditDto) {
        let data:{[key in keyof IotSim]? : IotSim[key]} = {}
        let fields = Object.keys(dto) as (keyof IotSim)[]
        const card = await this.iotSimModelService.findOne({id : id}, fields)
        if(!card) return false

        if(dto.expireIn) {
            dto.expireIn = dayjs(dto.expireIn).unix()
        }

        for(let k in card) {
            if(JSON.stringify(card[k]) != JSON.stringify(dto[k])) {
                data[k] = dto[k]
            }
        }

        if(Object.keys(data).length == 0) return true

        

        if(data.cardNo) {
            if((await this.cardNoIsExists(dto.cardNo)) == true) throw new Error('卡号已存在')
        }

        data.updateTime = getTime()

        let device = null

        if(data.cardNo) {
            device = await this.deviceModelService.findOne({simId : id}, ['deviceId', 'simCardNo'])
            if(device && (device.simCardNo != data.cardNo)) {
                const queryRunner = this.connection.createQueryRunner();
                await queryRunner.connect();
                await queryRunner.startTransaction()

                try {
                    
                    const { raw } = await queryRunner.manager.update<IotSim>(IotSim, {id : id}, data)
                    if(!raw || raw.affectedRows < 1) {
                        queryRunner.rollbackTransaction()
                        return false
                    }

                    {
                        const { raw } = await queryRunner.manager.update<Device>(Device, {deviceId : device.deviceId}, {simCardNo : data.cardNo})
                        if(!raw || raw.affectedRows < 1) {
                            queryRunner.rollbackTransaction()
                            return false
                        }
                    }

                    queryRunner.commitTransaction()

                    return true

                } catch (error) {
                    await queryRunner.rollbackTransaction()
                }finally {
                    await queryRunner.release()
                }

                return false

            }
        }else {
            let affectedRows = await this.iotSimModelService.update({id : id}, data)
            return affectedRows ? true : false
        }

        


        
    }
    
    async delete(ids:number[]) {
        try {
            let res = await this.iotSimModelService.delete(ids)
            if(res) return true
        } catch (error) {
            console.log(error.message)
        }
        return false
    }
}
